/**
 * MasicUtils
 * <p/>
 * User: joakimd
 * Date: 2013-03-11
 * Time: 15:09
 */
package org.dru.masic {
import flash.utils.Dictionary;

import org.dru.stk.StkUtils;

public final class MasicUtils {
    public function MasicUtils(guard: Guard) {
    }

    public static function getPortMixCode(target: MasicInput, source: MasicOutput): int {
        return (target.stereo ? 1 : 0) | (source.stereo ? 2 : 0);
    }

    public static function processSamples(target: MasicInput, start: int, end: int): void {
        if (!target.leased && target.numSources > 0) {
            var source: MasicOutput = target.getSourceAt(0);
            var code: int = getPortMixCode(target, source);
            switch (code) {
                case 0:
                default:
                    StkUtils.copy(target.left, source.left, start, end);
                    break;
                case 1:
                    StkUtils.copyM2S(target.left, target.right, source.left, start, end);
                    break;
                case 2:
                    StkUtils.copyS2M(target.left, source.left, source.right, start, end);
                    break;
                case 3:
                    StkUtils.copyS2S(target.left, target.right, source.left, source.right, start, end);
                    break;
            }
            for (var index: int = target.numSources; --index >= 1;) {
                source = target.getSourceAt(index);
                code = getPortMixCode(target, source);
                switch (code) {
                    case 0:
                    default:
                        StkUtils.add(target.left, source.left, start, end);
                        break;
                    case 1:
                        StkUtils.addM2S(target.left, target.right, source.left, start, end);
                        break;
                    case 2:
                        StkUtils.addS2M(target.left, source.left, source.right, start, end);
                        break;
                    case 3:
                        StkUtils.addS2S(target.left, target.right, source.left, source.right, start, end);
                        break;
                }
            }
        }
    }

    public static function compareComponentLength(c1: MasicComponent, c2: MasicComponent): int {
        const l1: int = getComponentLength(c1);
        const l2: int = getComponentLength(c2);
        return (l1 > l2 ? -1 : (l1 < l2 ? 1 : 0));
    }

    public static function getComponentLength(component: MasicComponent): int {
        return getComponentLengthImpl(component, new Dictionary(), 0);
    }

    private static function getComponentLengthImpl(component: MasicComponent, visited: Dictionary, length: int): int {
        var result: int = length;
        if (visited[component] == null) {
            visited[component] = component;
            const targetComponents: Vector.<MasicComponent> = getTargetComponents(component);
            for each (var targetComponent: MasicComponent in targetComponents) {
                result = Math.max(result, getComponentLengthImpl(targetComponent, visited, length + 1));
            }
        }
        return result;
    }

    public static function getTargetComponents(component: MasicComponent): Vector.<MasicComponent> {
        const result: Vector.<MasicComponent> = new Vector.<MasicComponent>();
        for each (var output: MasicOutput in component.outputs) {
            for each (var target: MasicInput in output.targets) {
                if (result.indexOf(target.parent) == -1) {
                    result.push(target.parent);
                }
            }
        }
        return result;
    }
}
}

class Guard {
}
